package org.opens.javaskill.thread.threadLocal;

import java.lang.reflect.Field;
import java.util.Random;

/**
 * @Date 2020/9/16 20:44
 * @Created by 99126
 */
public class ThreadLocalDemo2 {

    /**
     * 说明:
     * 1. ThreadLocal只需要一个实例, 就可以对多个线程提供存储服务, 并且彼此之间不干扰.
     */
    private final static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    private final static Random random = new Random(System.currentTimeMillis());

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            threadLocal.set(Thread.currentThread().getName());
            threadLocal.set("s1");
            threadLocal.set("s2");
            threadLocal.set("s3");
            threadLocal.set("s4");
            threadLocal.set("s5");
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            showMessage();
            System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
        }, "t1");

        Thread thread2 = new Thread(() -> {
            threadLocal.set(Thread.currentThread().getName());
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            showMessage();
            System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
        }, "t2");

        Thread thread3 = new Thread(() -> {
            threadLocal.set(Thread.currentThread().getName());
            threadLocal.set("s1");
            threadLocal.set("s2");
            threadLocal.set("s3");
            threadLocal.set("s4");
            threadLocal.set("s5");
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
        }, "t3");

        thread1.start();
        thread2.start();
        thread3.start();
        thread1.join();
        thread2.join();
        thread3.join();

        System.out.println("===");
        showMessage();

        System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
    }

    public static void showMessage() {
        try {
            Class<? extends Thread> aClass = Thread.currentThread().getClass();
            Field threadLocals = aClass.getDeclaredField("threadLocals");
            threadLocals.setAccessible(true);
            System.out.println(threadLocals.get(Thread.currentThread()));
            Object o = threadLocals.get(Thread.currentThread());
            System.out.println(o);
            Class<?> aClass1 = o.getClass();
            Field size = aClass1.getDeclaredField("size");
            size.setAccessible(true);
            System.out.println(Thread.currentThread().getName() + " size: " + size.get(threadLocals.get(Thread.currentThread())));

        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}
